home *** CD-ROM | disk | FTP | other *** search
/ BBS Toolkit / BBS Toolkit.iso / doors_2 / odoors41.zip / EZVOTE.C < prev    next >
C/C++ Source or Header  |  1993-02-26  |  24KB  |  501 lines

  1. /* EZVOTE.C - EZVote is an example door written in OpenDoors. This is a
  2.  *            relatively simple door that allows BBS users to vote anonymously
  3.  *            on various topics, entered by other users. Users are able to view
  4.  *            the results of voting on a topics, only if they have already
  5.  *            voted on the topic, and may only vote on each topic once. The
  6.  *            door automatically uses ANSI or AVATAR graphics if available, and
  7.  *            will work with nearly any BBS system. When in the door, the sysop
  8.  *            (automatically detected by comparing user name to sysop name)
  9.  *            also has the option of deleting existing questions.
  10.  *
  11.  *            EZVote also provides all of the features that are available in
  12.  *            any OpenDoors door, without any extra effort on the part of the
  13.  *            programmer. These features include sysop chatting, paging, full
  14.  *            status line, shell to DOS, time adjusting, hangup & lockout, and
  15.  *            other function keys. It does, of course, properly monitor carrier
  16.  *            detect, user inactivity and user time left. EZVote also runs very
  17.  *            quickly and reliably is automatically DesqView aware. EZVote will
  18.  *            also function perfectly normally in local mode.
  19.  *
  20.  *            In addition to these features, EZVote's operation can be
  21.  *            customized using the EZVOTE.CFG file. This accompanying
  22.  *            configuration file is automatically read by OpenDoor's built in
  23.  *            configuration file system. EZVote also makes use of OpenDoor's
  24.  *            logfile sub-system.
  25.  *
  26.  *            EZVote will exit with one of the following errorlevels:
  27.  *                        0 - Critical Door error (no fossil, etc.)
  28.  *                        1 - Carrier lost, user off-line
  29.  *                        2 - Sysop terminated call, user off-line
  30.  *                        3 - User time used up, user STILL ON-LINE
  31.  *                        4 - Keyboard inactivity timeout, user off-line
  32.  *                        5 - Sysop dropped user back to BBS, user ON-LINE
  33.  *                       10 - User chose to return to BBS
  34.  *                       11 - User chose to logoff, user off-line
  35.  *                       12 - Critical EZVote error
  36.  *
  37.  *            EZVote may be recompiled or changed as you wish, under the
  38.  *            conditions of the OpenDoors "licence" (ie, if you haven't
  39.  *            registered, you can not distribute any doors compiled in
  40.  *            OpenDoors, and may only use OpenDoors for a three week evaluation
  41.  *            period). If you wish to compile EZVote, as with any OpenDoors
  42.  *            door, all you must do is to ensure OPENDOOR.H is present in the
  43.  *            default directory, and that Turbo C(++) / Borland C++ is
  44.  *            configured to link your program with the appropriate OpenDoors
  45.  *            library file. For more detailed information on this example
  46.  *            program please see the OPENDOORS.DOC file.
  47.  */
  48.  
  49.  
  50. #include <conio.h>
  51. #include <io.h>
  52. #include <fcntl.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include <sys\stat.h>
  56. #include <alloc.h>
  57.  
  58. #include "opendoor.h"                        /* Must be included in all doors */
  59.  
  60.  
  61. char menu_text=0x02;                      /* EZVote default display colours */
  62. char menu_highlight=0x0a;
  63. char input_colour=0x0f;
  64. char title_text=0x0c;
  65. char title_lines=0x04;
  66. char copyright_colour=0x04;
  67. char list_colour=0x02;
  68.  
  69.  
  70. void   choose_topic(int mode);            /* Allows user to choose a question */
  71. void   display_results(void);           /* Displays the results of a question */
  72. void   vote(void);                                  /* Places the user's vote */
  73. int    add_answer(void);                 /* Adds a new answer to the question */
  74. void   save_file(void);                          /* Saves the EZVOTE.BBS file */
  75. void   delete_question(void);             /* Removes a question from the file */
  76. void   main_menu(void);                      /* Displays the EZVote main menu */
  77.  
  78.  
  79. struct file_struct                                  /* EZVOTE.BBS file format */
  80.    {
  81.    int    num_questions;                   /* Number of questions in the file */
  82.    char   quest_title[20][60],                /* The "Title" of each question */
  83.           quest_by[20][36],                        /* Who wrote each question */
  84.           quest_text[20][60];                   /* The actual question itself */
  85.    int    quest_num_ans[20];          /* The number of answers to each quest. */
  86.    char   quest_answers[20][20][60];  /* The possible answers for each quest. */
  87.    int    total_votes[20],             /* # of times quest. has been voted on */
  88.           votes[20][20],               /* # of votes each chioce has recieved */
  89.           num_users;                    /* Number of users who have used door */
  90.    char   user[200][36],                                  /* Each user's name */
  91.           voted[200][20];             /* Has the user voted on each question? */
  92.    } *file;
  93.  
  94.                                                 /* Variables used by the door */
  95. int handle, counter, usernum, topic, choice, key, sysop;
  96. char string[80];
  97.  
  98.  
  99. main()
  100.     {                        /* Attempt to allocate memory for file structure */
  101.     if((file=malloc(sizeof(struct file_struct)))==NULL)
  102.        {
  103.        printf("Not enough available memory for EZVote for run!\n");
  104.        return(12);
  105.        }
  106.  
  107.  
  108.     strcpy(od_registered_to,"[Unregistered]"); /* OpenDoors registration info */
  109.     od_registration_key=000000000000;
  110.  
  111.     strcpy(od_program_name,"EZVote 4.10");            /* Name of door program */
  112.  
  113.  
  114.              /* Initialize OpenDoors, using the configuration file EZVOTE.CFG */
  115.     od_init_with_config("EZVOTE.CFG",NULL);
  116.  
  117.  
  118.     od_log_open();     /* Open the log file and begin logging door activities */
  119.  
  120.  
  121.  
  122. /* Cause OpenDoors to call the save_file() function before exiting, under any
  123.  * circumstances. This way, the EZVOTE.BBS data file will be saved, even if
  124.  * if the user looses connection.
  125.  */
  126.     od_control.od_before_exit=save_file;
  127.  
  128.  
  129.                                              /* Open the EZVOTE.BBS data file */
  130.     if((handle=open("EZVOTE.BBS",O_RDONLY|O_BINARY))==-1)
  131.        {                              /* Create the file if it does not exist */
  132.        od_log_write("EZVOTE.BBS data file not found, creating new one");
  133.        handle=open("EZVOTE.BBS",O_RDWR|O_BINARY|O_CREAT,S_IWRITE|S_IREAD);
  134.        file->num_questions=0; /* Blank file to zero questions, and zero users */
  135.        file->num_users=0;
  136.        write(handle,file,sizeof(struct file_struct));
  137.        }
  138.     else                                  /* Read data from file if it exists */
  139.        read(handle,file,sizeof(struct file_struct));
  140.     close(handle);                                    /* Close the file again */
  141.  
  142.                                              /* Search for user in EZVOTE.BBS */
  143.     for(usernum=0;usernum<file->num_users;++usernum)
  144.        if(strcmp(file->user[usernum],od_control.user_name)==0) break;
  145.  
  146.     if(usernum==file->num_users)         /* If user hasn't used EZVote before */
  147.        {                                           /* Add him/her to the file */
  148.        if(++file->num_users>200) od_exit(12,FALSE);
  149.        strcpy(file->user[usernum],od_control.user_name);
  150.        for(counter=0;counter<20;++counter)
  151.           file->voted[usernum][counter]=FALSE;
  152.        }
  153.                                             /* Check if the user is the sysop */
  154.     sysop=strcmp(od_control.user_name,od_control.sysop_name)==0;
  155.  
  156.     do
  157.        {
  158.        main_menu();                                  /* Display the main menu */
  159.  
  160.        od_set_attrib(input_colour);     /* Display prompt with time remaining */
  161.        od_printf("Select Command (%d mins)\n\r",od_control.user_timelimit);
  162.        od_set_attrib(menu_text);
  163.  
  164.                                                          /* Get user's choice */
  165.        switch(key=od_get_answer("vrapdqg\n\r"))
  166.           {
  167.           case 'v':            /* If user pressed V key (upper or lower case) */
  168.              do
  169.                 {                  /* Allow user to choose a topic to vote on */
  170.                 choose_topic(FALSE);
  171.  
  172.                                                   /* If valid topic # entered */
  173.                 if(topic>=0 && topic<=19)
  174.                    {                      /* Display the question to the user */
  175.                    od_set_attrib(title_text);
  176.                    od_disp_str("\n\r\n\r");od_clr_scr();
  177.                    od_disp_str(file->quest_text[topic]);
  178.                    od_disp_str("\n\r");
  179.                    od_set_attrib(list_colour);
  180.  
  181.                                           /* Display possible answers to user */
  182.                    for(counter=0;counter<file->quest_num_ans[topic];++counter)
  183.                       {
  184.                       od_printf("    %2d.) %s\n\r",counter+1,file->quest_answers[topic][counter]);
  185.                       }
  186.                                                          /* Get user's choice */
  187.                    od_set_attrib(input_colour);
  188.                    od_disp_str("\n\rSelect answer, [O] for other, or [Enter] to pass: ");
  189.  
  190.                         /* Allow user to input choice of up to two characters */
  191.                    od_input_str(string,2,32,127);
  192.                    choice=atoi(string)-1;
  193.  
  194.                                            /* If user selected "other" option */
  195.                    if(string[0]=='o' || string[0]=='O')
  196.                       {                      /* If room to add another answer */
  197.                       if(file->quest_num_ans[topic]<20)
  198.                          {         /* Allow user to add an answer to question */
  199.                          od_disp_str("\n\r\n\rWhat is your \"Other\" answer?\n\r");
  200.                          if(add_answer())
  201.                             {                /* If user actually added answer */
  202.                             choice=file->quest_num_ans[topic]-1;
  203.                             vote();                     /* Record user's vote */
  204.                             }
  205.                          }
  206.                       else            /* If there is no room for more answers */
  207.                          {                           /* Indicate this to user */
  208.                          od_disp_str("\n\r\n\rThis question already has 20 answers!\n\r");
  209.                          od_disp_str("Press any key to continue...\n\r");
  210.                          od_get_key(TRUE);
  211.                          }
  212.                       }
  213.  
  214.                    else                /* If user voted for a possible option */
  215.                       {
  216.                       if(choice>=0 && choice<=file->quest_num_ans[topic])
  217.                          {
  218.                          vote();                        /* Record user's vote */
  219.                          }
  220.                       }
  221.                    }
  222.  
  223.                 } while(topic!=-1);     /* Loop until user is finished voting */
  224.              break;
  225.  
  226.  
  227.           case 'r':                       /* If user wants to display results */
  228.              for(;;)
  229.                 {
  230.                 choose_topic(TRUE);           /* Allow user to choose a topic */
  231.                 if(topic==-1) break;     /* Exit loop if user wishes to abort */
  232.                 display_results();             /* Display results of question */
  233.                 }
  234.              break;
  235.  
  236.  
  237.           case 'a':                               /* If adding a new question */
  238.              od_clr_scr();                   /* Clear the screen (if enabled) */
  239.  
  240.                                      /* If there is room for another question */
  241.              if(file->num_questions<20)
  242.                 {
  243.                                    /* Store user's name as author of question */
  244.                 strcpy(file->quest_by[file->num_questions],od_control.user_name);
  245.                 file->total_votes[file->num_questions]=0;
  246.  
  247.                                               /* Get question title from user */
  248.                 od_disp_str("\n\r\n\rWhat is the title of your question?\n\r > ");
  249.                 od_set_attrib(input_colour);
  250.                 od_input_str(string,59,32,127);
  251.                 od_set_attrib(menu_text);
  252.                 strcpy(file->quest_title[file->num_questions],string);
  253.  
  254.                 if(strlen(string)!=0)                /* If user did not abort */
  255.                    {                     /* Get the question itself from user */
  256.                    od_disp_str("\n\rWhat is your question?\n\r > ");
  257.                    od_set_attrib(input_colour);
  258.                    od_input_str(string,59,32,127);
  259.                    od_set_attrib(menu_text);
  260.                    strcpy(file->quest_text[file->num_questions],string);
  261.                                                      /* If user did not abort */
  262.                    if(strlen(string)!=0)
  263.                       {                           /* Get the possible answers */
  264.                       od_disp_str("\n\rNow, enter the possible answers to your question:\n\r");
  265.                       topic=file->num_questions;
  266.                       file->quest_num_ans[topic]=0;
  267.                       while(add_answer());
  268.  
  269.                                                  /* Confirm question creation */
  270.                       od_set_attrib(menu_text);
  271.                       od_disp_str("Do you wish to save this question? (Y/N) ");
  272.                       choice=od_get_answer("yn");
  273.  
  274.                       if(choice=='y')                         /* If confirmed */
  275.                          {
  276.                          file->num_questions++;    /* Make addition permanent */
  277.                                                /* Record addition in log file */
  278.                          od_log_write("User created new question");
  279.                          }
  280.                       }
  281.                    }
  282.                 }
  283.              else               /* If no room for a new question, inform user */
  284.                 {
  285.                 od_disp_str("Sorry, EZVote has a limit of 20 questions.\n\r");
  286.                 od_disp_str("Press any key to continue...\n\r\n\r");
  287.                 od_log_write("User attempting to create new question, 20 question limit reached");
  288.                 od_get_key(TRUE);
  289.                 }
  290.  
  291.              break;
  292.  
  293.  
  294.           case 'p':                        /* If user wants to page the sysop */
  295.              od_page();                   /* OpenDoors takes care of the rest */
  296.              break;
  297.  
  298.           case 'd':                             /* If user pressed delete key */
  299.              if(sysop)                                  /* If it is the sysop */
  300.                 {
  301.                 od_clr_scr();                             /* Clear the screen */
  302.  
  303.                                               /* Ask which question to delete */
  304.                 od_disp_str("Please enter question number to delete: ");
  305.                 od_set_attrib(input_colour);
  306.                 od_input_str(string,2,'0','9');
  307.                 topic=atoi(string)-1;
  308.                 od_set_attrib(menu_text);
  309.                                                            /* If valid choice */
  310.                 if(topic>=0 && topic<file->num_questions)
  311.                    {                             /* Confirm question deletion */
  312.                    od_printf("\n\r\n\r Delete: %s\n\r\n\r",file->quest_title[topic]);
  313.                    od_set_attrib(title_text);
  314.                    od_disp_str("Are You Sure? (Y/N)\n\r");
  315.                    od_set_attrib(menu_text);
  316.                    choice=od_get_answer("yn");
  317.  
  318.                                              /* If confirmed, delete question */
  319.                    if(choice=='y') delete_question();
  320.                    }
  321.                 }
  322.           }                               /* Loop until quit to BBS or logoff */
  323.        } while(key!='q' && key!='g');
  324.  
  325.     if(key=='g')                                /* If user wishsed to log off */
  326.        {                                            /* Display "goodbye" line */
  327.        od_printf("\n\rGoodbye from %s...\n\r",od_control.system_name);
  328.        od_exit(11,TRUE);               /* Let OpenDoors take care of the rest */
  329.        }
  330.     else
  331.        {                                         /* Acknowledge return to BBS */
  332.        od_printf("\n\rReturning you to %s...\n\r",od_control.system_name);
  333.        od_exit(10,FALSE);                    /* Again OpenDoors does the rest */
  334.        }
  335.  
  336.     return(0);
  337.     }
  338.  
  339.  
  340. void save_file(void)                      /* Function to save EZVOTE.BBS file */
  341.    {                                      /* (called before door termination) */
  342.    handle=open("EZVOTE.BBS",O_WRONLY|O_BINARY);
  343.    write(handle,file,sizeof(struct file_struct));
  344.    close(handle);
  345.    }
  346.  
  347.  
  348. int add_answer(void)                        /* Function to add answer to file */
  349.    {                                          /* Check for room to add answer */
  350.    if(file->quest_num_ans[topic]>=20) return(FALSE);
  351.  
  352.    od_set_attrib(menu_text);                             /* Get user's answer */
  353.    od_printf(" %2d> ",file->quest_num_ans[topic]+1);
  354.    od_set_attrib(input_colour);
  355.    od_input_str(string,59,32,127);
  356.    if(strlen(string)==0) return(FALSE);
  357.                                               /* If no abort, add to question */
  358.    file->votes[topic][file->quest_num_ans[topic]]=0;
  359.    strcpy(file->quest_answers[topic][file->quest_num_ans[topic]++],string);
  360.    return(TRUE);
  361.    }
  362.  
  363.  
  364.  
  365. void choose_topic(int mode)        /* Function to let user to choose question */
  366.    {
  367.    register char displayed=FALSE;
  368.  
  369.    for(;;)
  370.       {
  371.       od_set_attrib(title_text);
  372.       od_clr_scr();                                       /* Clear the screen */
  373.       od_disp_str("Choose A Topic:\n\r");
  374.       od_set_attrib(list_colour);
  375.                                                          /* Display questions */
  376.       for(counter=0;counter<file->num_questions;++counter)
  377.          {                                 /* If question should be displayed */
  378.          if(file->voted[usernum][counter]==mode)
  379.             {
  380.             displayed=TRUE;                               /* Display question */
  381.             od_printf("    %d.) %s\n\r",counter+1,file->quest_title[counter]);
  382.             }
  383.          }
  384.                                             /* if no topics were displayed... */
  385.       if(!displayed) od_disp_str("\n\r    No Topics to choose from.\n\r\n\r");
  386.  
  387.       od_set_attrib(input_colour);
  388.       od_disp_str("Select topic, or [Enter] to return to main menu: ");
  389.  
  390.       od_input_str(string,2,'0','9');                    /* Get user's choice */
  391.  
  392.       topic=atoi(string)-1;                       /* Convert string to number */
  393.  
  394.       if(topic==-1) return;                          /* If user aborted, exit */
  395.                                                    /* If valid question, exit */
  396.       if(topic<file->num_questions && topic>=0 && file->voted[usernum][topic]==mode) return;
  397.       }
  398.    }
  399.  
  400.  
  401.  
  402. void display_results(void)         /* Function to display results of question */
  403.    {
  404.    od_set_attrib(title_text);                           /* Display the header */
  405.    od_clr_scr();
  406.    od_disp_str(file->quest_title[topic]);
  407.    od_set_attrib(title_lines);
  408.    od_printf("\n\r(Created by: %s)\n\r",file->quest_by[topic]);
  409.  
  410.    od_set_attrib(list_colour);
  411.                            /* Loop through each answer, displaying statistics */
  412.    for(counter=0;counter<file->quest_num_ans[topic];++counter)
  413.       od_printf("  %-3d  %3d%%   %s\n\r",file->votes[topic][counter],(file->votes[topic][counter]*100)/file->total_votes[topic],file->quest_answers[topic][counter]);
  414.  
  415.    od_set_attrib(input_colour);
  416.                                               /* Wait for user to press a key */
  417.    od_disp_str("\n\rPress [Enter] continue...");
  418.    od_get_answer("\n\r");
  419.    od_disp_str("\n\r\n\r");
  420.    }
  421.  
  422.  
  423.  
  424. void vote(void)                             /* Function to record user's vote */
  425.    {
  426.    file->voted[usernum][topic]=TRUE;     /* Stop user from voting on it again */
  427.    ++file->total_votes[topic];              /* Increase total number of votes */
  428.    ++file->votes[topic][choice];                           /* Add user's vote */
  429.    display_results();                /* Show user results of question to date */
  430.    }
  431.  
  432.  
  433.  
  434. void delete_question(void)                   /* Function to delete a question */
  435.    {
  436.    if(topic==--file->num_questions) return;
  437.    memcpy(file->quest_title[topic],file->quest_title[topic+1],60*(19-topic));
  438.    memcpy(file->quest_by[topic],file->quest_by[topic+1],36*(19-topic));
  439.    memcpy(file->quest_text[topic],file->quest_text[topic+1],60*(19-topic));
  440.    memcpy(&file->quest_num_ans[topic],&file->quest_num_ans[topic+1],2*(19-topic));
  441.    memcpy(file->quest_answers[topic],file->quest_answers[topic+1],1200*(19-topic));
  442.    memcpy(&file->total_votes[topic],&file->total_votes[topic+1],2*(19-topic));
  443.    memcpy(file->votes[topic],file->votes[topic+1],40*(19-topic));
  444.    for(counter=0;counter<file->num_users;++counter)
  445.       memcpy(&file->voted[counter][topic],&file->voted[counter][topic+1],19-topic);
  446.    }
  447.  
  448.  
  449.  
  450. void main_menu(void)                     /* Function to display the main menu */
  451.    {
  452.    od_clear_keybuffer();  /* Remove any waiting keypresses in keyboard buffer */
  453.  
  454.    od_clr_scr();                                              /* Clear screen */
  455.  
  456.  
  457.   /* Use EZVOTE.ASC/ANS/AVT to display the menu, if one of these files exists */
  458.    if(od_send_file("EZVOTE")) return;
  459.  
  460.                                           /* Otherwise, display built-in menu */
  461.  
  462.    else if(od_control.user_ansi)         /* Display graphics title if ANSI or */
  463.       {                                         /* AVATAR modes are available */
  464.       od_set_attrib(title_lines);
  465.       od_disp_str("\n\r───────────────────────────────────────────────────────────────────────────────\n\r");
  466.       od_set_attrib(title_text);
  467.       od_disp_str("                      EZVote ■ OpenDoors 4.10 Example Door");
  468.       od_set_attrib(title_lines);
  469.       od_disp_str("\n\r───────────────────────────────────────────────────────────────────────────────\n\r");
  470.       od_set_attrib(copyright_colour);
  471.       od_set_cursor(5,25);
  472.       od_disp_str("Copyright 1993 by Brian Pirie\n\r\n\r\n\r");
  473.       }
  474.    else       /* Display non-graphics title if graphics mode is not available */
  475.       {
  476.       od_disp_str("\n\r-------------------------------------------------------------------------------\n\r");
  477.       od_disp_str("                      EZVote - OpenDoors 4.10 Example Door");
  478.       od_disp_str("\n\r-------------------------------------------------------------------------------\n\r");
  479.       od_disp_str("                         Copyright 1993 by Brian Pirie\n\r\n\r\n\r");
  480.       }
  481.  
  482.    od_set_attrib(menu_text);      od_disp_str("\n\r                           [");
  483.    od_set_attrib(menu_highlight); od_disp_str("V");
  484.    od_set_attrib(menu_text);      od_disp_str("] Vote on a Topic\n\r                           [");
  485.    od_set_attrib(menu_highlight); od_disp_str("R");
  486.    od_set_attrib(menu_text);      od_disp_str("] View results\n\r                           [");
  487.    od_set_attrib(menu_highlight); od_disp_str("A");
  488.    od_set_attrib(menu_text);      od_disp_str("] Add a new question\n\r                           [");
  489.    od_set_attrib(menu_highlight); od_disp_str("P");
  490.    od_set_attrib(menu_text);      od_disp_str("] Page Sysop\n\r                           [");
  491.    if(sysop)
  492.       {
  493.       od_set_attrib(menu_highlight); od_disp_str("D");
  494.       od_set_attrib(menu_text);      od_disp_str("] Delete Booth\n\r                           [");
  495.       }
  496.    od_set_attrib(menu_highlight); od_disp_str("G");
  497.    od_set_attrib(menu_text);      od_disp_str("] Goodbye (Logoff)\n\r                           [");
  498.    od_set_attrib(menu_highlight); od_disp_str("Q");
  499.    od_set_attrib(menu_text);      od_disp_str("] Return to BBS\n\r\n\r\n\r");
  500.    }
  501.